home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 350_01 / pcx_file.c < prev    next >
C/C++ Source or Header  |  1991-11-29  |  50KB  |  1,378 lines

  1. /*
  2.  *************************************************************************
  3.  *
  4.  *  PCX_FILE.C - PCX_LIB Library Image File Functions
  5.  *
  6.  *  Version:    1.00C
  7.  *
  8.  *  History:    91/02/14 - Created
  9.  *              91/04/01 - Release 1.00A
  10.  *              91/04/03 - Fixed "segread" call.
  11.  *              91/04/07 - Release 1.00B
  12.  *              91/11/18 - Fixed "pcx_init_palette" and "pcx_write_extpal"
  13.  *                         for large memory model.
  14.  *                       - Made default EGA palette register values
  15.  *                           array "_far".
  16.  *              91/12/01 - Release 1.00C
  17.  *
  18.  *  Compiler:   Microsoft C V6.0
  19.  *
  20.  *  Author:     Ian Ashdown, P.Eng.
  21.  *              byHeart Software
  22.  *              620 Ballantree Road
  23.  *              West Vancouver, B.C.
  24.  *              Canada V7S 1W3
  25.  *              Tel. (604) 922-6148
  26.  *              Fax. (604) 987-7621
  27.  *
  28.  *  Copyright:  Public Domain
  29.  *
  30.  *************************************************************************
  31.  */
  32.  
  33. /*
  34.  *************************************************************************
  35.  *
  36.  *  PORTABILITY NOTES
  37.  *
  38.  *  1.  While this program is written in ANSI C, it uses a number of 
  39.  *      function calls that are specific to the Microsoft C V6.0 library.
  40.  *      These are documented as follows for the purposes of porting this
  41.  *      program to other compilers and/or processors: 
  42.  *
  43.  *          _ffree      - "free" for small model / far data
  44.  *          _fmalloc    - "malloc" for small model / far data
  45.  *          _fmemcpy    - "memcpy" for small model / far data
  46.  *          int86       - execute 80x86 interrupt routine
  47.  *          int86x      - execute 80x86 interrupt routine (far data)
  48.  *          outpw       - output word to 80x86 I/O port
  49.  *
  50.  *  2.  When porting this program to other processors, remember that words
  51.  *      are stored by 80x86-based machines in the big-endian format.  That
  52.  *      is, the eight least significant bits (lower byte) are stored
  53.  *      first, followed by the eight most significant bits (upper byte).
  54.  *      If PCX-format files are transferred to little-endian machines
  55.  *      (such as those based on 680x0 and Z8000 processors), the order of
  56.  *      bytes within each word will have to be reversed before they can 
  57.  *      be interpreted.  (This applies to the file header only, since the
  58.  *      encoded image data and optional 256-color palette are stored as
  59.  *      bytes.)
  60.  *
  61.  * 3.   MS-DOS does not recognize the 720 x 348 graphics mode of the
  62.  *      Hercules monochrome display adapter.  Therefore, the constant
  63.  *      PCX_HERC should never be passed as a video mode parameter to any
  64.  *      BIOS service routine.
  65.  *
  66.  *      The Microsoft C compiler includes a "video mode" parameter
  67.  *      definition (_HERCMONO) that is defined as 0x08.  This is a
  68.  *      reserved MS-DOS video mode that is apparently used internally by
  69.  *      the ROM BIOS.  It can, however, be passed to the Microsoft C
  70.  *      library function "_setvideomode" to force the Hercules display
  71.  *      adapter into graphics mode.
  72.  *
  73.  *      Most other MS-DOS C compilers offer similar library functions to
  74.  *      force the Hercules monochrome display adapter into its 720 x 348
  75.  *      graphics mode.
  76.  *
  77.  ************************************************************************* 
  78.  */
  79.  
  80. /*      INCLUDE FILES                                                   */
  81.  
  82. #include <stdio.h>
  83. #include <stdlib.h>
  84. #include <string.h>
  85. #include <conio.h>
  86. #include <malloc.h>
  87. #include <dos.h>
  88. #include <graph.h>
  89. #include "pcx_int.h"
  90.  
  91. /*      FORWARD REFERENCES                                              */
  92.  
  93. static BOOL pcx_encode(int, int, FILE *);
  94. static BOOL pcx_init_palette(PCX_PAL *, int);
  95. static BOOL pcx_write_extpal(FILE *);
  96. static BOOL pcx_write_line(unsigned char *, int, FILE *);
  97. static BOOL pcx_write_init(PCX_WORKBLK *, int, int, int, int);
  98.  
  99. static void pcx_get_cga(PCX_WORKBLK *, unsigned char _far *, int);
  100. static void pcx_get_ega(PCX_WORKBLK *, unsigned char _far *, int);
  101. static void pcx_get_herc(PCX_WORKBLK *, unsigned char _far *, int);
  102. static void pcx_get_vga(PCX_WORKBLK *, unsigned char _far *, int);
  103.  
  104. /*      GLOBALS                                                         */
  105.  
  106. /* Default EGA palette register values                                  */
  107.  
  108. static BYTE _far pcx_EGA_DefPal_1[16] =         /* Modes 0x0d and 0x0e  */
  109. {
  110.   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
  111.   0x14, 0x15, 0x16, 0x17
  112. };
  113.  
  114. static BYTE _far pcx_EGA_DefPal_2[16] =         /* Mode 0x0f            */
  115. {
  116.   0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
  117.   0x00, 0x18, 0x00, 0x00
  118. };
  119.  
  120. static BYTE _far pcx_EGA_DefPal_3[16] =         /* Mode 0x10            */
  121. {
  122.   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a, 0x3b, 
  123.   0x3c, 0x3d, 0x3e, 0x3f
  124. };
  125.  
  126. /*      PUBLIC FUNCTIONS                                                */
  127.  
  128. /*
  129.  *************************************************************************
  130.  *
  131.  *  PCX_WRITE - Write PCX File
  132.  *
  133.  *  Purpose:    To write a PCX-format image file from an image stored in
  134.  *              a video buffer.  The image is assumed to start in the
  135.  *              upper left corner of the screen.
  136.  *
  137.  *  Setup:      BOOL pcx_write
  138.  *              (
  139.  *                char *fname,
  140.  *                int vmode,
  141.  *                int page,
  142.  *                int width,
  143.  *                int height,
  144.  *              )
  145.  *
  146.  *  Where:      fname is a PCX image file name.
  147.  *              vmode is the MS-DOS video mode.  Valid values are:
  148.  *
  149.  *                PCX_HERC -    720 x 348 Hercules monochrome
  150.  *                0x04 -        320 x 200 4-color CGA
  151.  *                0x05 -        320 x 200 4-color CGA (color burst off)
  152.  *                0x06 -        640 x 200 2-color CGA
  153.  *                0x0d -        320 x 200 16-color EGA/VGA
  154.  *                0x0e -        640 x 200 16-color EGA/VGA
  155.  *                0x0f -        640 x 350 2-color EGA/VGA
  156.  *                0x10 -        640 x 350 16-color EGA/VGA
  157.  *                0x11 -        640 x 480 2-color VGA
  158.  *                0x12 -        640 x 480 16-color VGA
  159.  *                0x13 -        320 x 200 256-color VGA
  160.  *
  161.  *              page is the video display page number.  Valid values are:
  162.  *
  163.  *                Mode PCX_HERC - 0 or 1
  164.  *                Mode 0x0d     - 0 to 7
  165.  *                Mode 0x0e     - 0 to 3
  166.  *                Mode 0x0f     - 0 or 1
  167.  *                Mode 0x10     - 0 or 1
  168.  *                All Other     - 0
  169.  *
  170.  *              width is the image width in pixels.
  171.  *              height is the image height in pixels.
  172.  *
  173.  *  Return:     TRUE if successful; otherwise FALSE.
  174.  *
  175.  *************************************************************************
  176.  */
  177.  
  178. BOOL pcx_write
  179. (
  180.   char *fname,
  181.   int vmode,
  182.   int page,
  183.   int width,
  184.   int height
  185. )
  186. {
  187.   int bpline;                   /* Number of bytes per scan line        */
  188.   int line_num;                 /* Scan line number                     */
  189.   unsigned char *linep;         /* Image scan line buffer pointer       */
  190.   BOOL status = TRUE;           /* Return status                        */
  191.   PCX_WORKBLK *wbp;             /* PCX image file workblock pointer     */
  192.  
  193.   /* Open a PCX image file workblock                                    */
  194.  
  195.   if ((wbp = pcx_open(fname, TRUE)) == (PCX_WORKBLK *) NULL)
  196.     return (FALSE);
  197.  
  198.   /* Initialize the workblock for writing                               */
  199.  
  200.   if (pcx_write_init(wbp, vmode, page, width, height) == FALSE)
  201.     status = FALSE;
  202.  
  203.   /* Calculate number of bytes per line (for all color planes)          */
  204.  
  205.   bpline = wbp->header.bppscan * wbp->header.nplanes;
  206.  
  207.   /* Allocate a scan line buffer                                        */
  208.  
  209.   if (status == TRUE)
  210.     if ((linep = (unsigned char *) malloc(bpline)) == (unsigned char *)
  211.         NULL)
  212.       status = FALSE;
  213.  
  214.   /* Write the file header to the file                                  */
  215.  
  216.   if (sta